﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

using System.Xml;

namespace Transformer.iHunter.Plugins.BBS
{
    public partial class BbsItemEditor : UserControl, Transformer.iHunter.UI.IFieldTextBoxOwner
    {
        private Control lastControlFocused = null;
        private bool needNotifyMsgInvalidReason = false;
        
        private bool isMail;
        private string errorReason;
        private bool modified;
        private bool isReply = false;

        private Transformer.iHunter.UI.FieldTextBox textBox_Receiver;
        private Transformer.iHunter.UI.FieldTextBox textBox_Title;
        private Transformer.iHunter.UI.FieldTextBox textBox_Board;
        private Transformer.iHunter.UI.FieldTextBox textBox_ReplyTo;

        public BbsItemEditor()
        {
            InitializeComponent();

            Init();
        }

        private void Init()
        {
            textBox_Receiver = new Transformer.iHunter.UI.FieldTextBox(this, "Receiver");
            textBox_Title = new Transformer.iHunter.UI.FieldTextBox(this, "Title");
            textBox_ReplyTo = new Transformer.iHunter.UI.FieldTextBox(this, "ReplyTo");
            textBox_Board = new Transformer.iHunter.UI.FieldTextBox(this, "Board");

            textBox_Receiver.Dock = DockStyle.Fill;
            textBox_ReplyTo.Dock = DockStyle.Fill;
            textBox_Title.Dock = DockStyle.Fill;
            textBox_Board.Dock = DockStyle.Fill;

            textBox_Contents.SetOwner(this, "Press ESC to insert control char");            
            textBox_Contents.EnableTip = true;

            textBox_ReplyTo.ReadOnly = true;
            tableLayoutPanel_Fields.Controls.Add(textBox_Receiver, 2, 1);
            tableLayoutPanel_Fields.Controls.Add(textBox_ReplyTo, 2, 2);
            tableLayoutPanel_Fields.Controls.Add(textBox_Board, 2, 3);
            tableLayoutPanel_Fields.Controls.Add(textBox_Title, 2, 4);

            isMail = false;
            comboBox_Type.SelectedIndex = 0;

            modified = false;
        }

        #region IFieldTextBoxOwner Members

        public void EnableClipboardButtons(bool cut, bool undo, bool redo)
        {
            if (this.UpdateCommandUI != null)
            {
                CommandUIEventArgs updateArgs = new CommandUIEventArgs();
                updateArgs.Name = "Edit.Cut";
                updateArgs.Enabled = cut;
                updateArgs.Mask = CommandUIMask.None | CommandUIMask.Enabled;

                this.UpdateCommandUI(this, updateArgs);

                updateArgs.Name = "Edit.Copy";
                this.UpdateCommandUI(this, updateArgs);

                updateArgs.Name = "Edit.Paste";
                updateArgs.Enabled = Clipboard.ContainsText();
                this.UpdateCommandUI(this, updateArgs);

                updateArgs.Name = "Edit.Undo";
                updateArgs.Enabled = undo;
                this.UpdateCommandUI(this, updateArgs);

                updateArgs.Name = "Edit.Redo";
                updateArgs.Enabled = redo;
                this.UpdateCommandUI(this, updateArgs);
            }
        }

        public void DisableClipboardButtons()
        {
            if (this.UpdateCommandUI != null)
            {
                CommandUIEventArgs updateArgs = new CommandUIEventArgs();
                updateArgs.Name = "Edit.Cut";
                updateArgs.Enabled = false;
                updateArgs.Mask = CommandUIMask.None | CommandUIMask.Enabled;

                this.UpdateCommandUI(this, updateArgs);

                updateArgs.Name = "Edit.Copy";
                this.UpdateCommandUI(this, updateArgs);

                updateArgs.Name = "Edit.Paste";
                updateArgs.Enabled = false;
                this.UpdateCommandUI(this, updateArgs);

                updateArgs.Name = "Edit.Undo";
                updateArgs.Enabled = false;
                this.UpdateCommandUI(this, updateArgs);

                updateArgs.Name = "Edit.Redo";
                updateArgs.Enabled = false;
                this.UpdateCommandUI(this, updateArgs);
            }
        }

        public void EnterFieldTextBox(Transformer.iHunter.UI.FieldTextBox txtBox)
        {
            lastControlFocused = txtBox;
        }

        public void MarkMessageModified()
        {
            modified = true;
        }

        #endregion

        private void ShowMessageInvalidReason(Transformer.iHunter.UI.FieldTextBox txtBox, string reason)
        {
            if (needNotifyMsgInvalidReason)
            {
                txtBox.ShowTip(reason);
            }
        }


        #region IMessageEditor Members

        public IMessage GetMessage()
        {
            needNotifyMsgInvalidReason = true;
            bool msgValid = MessageValid;
            needNotifyMsgInvalidReason = false;
            if (msgValid)
            {
                IMessage msg = new Message();

                if (isReply)
                {
                    if (isMail)
                    {
                        msg.Receiver = textBox_ReplyTo.Text;
                        msg.Category = Mail.MailCategory;
                    }
                    else
                    {
                        msg.Category = textBox_Board.Text;
                    }
                }
                else
                {
                    if (isMail)
                    {
                        msg.Receiver = textBox_Receiver.Text;
                        msg.Category = Mail.MailCategory;
                    }
                    else
                    {
                        msg.Category = textBox_Board.Text;
                    }
                }

                msg.Title = textBox_Title.Text;
                msg.Content = textBox_Contents.Text.Replace(Character.ESC + "", Character.DoubleESC);
                msg.ViewerGuid = new Guid("751B6808-5676-43b6-B9B7-B167CF9743F4");
                msg.EditorGuid = BbsItemEditorProvider.Guid;
                return msg;
            }
            else
            {
                //MessageBox.Show(errorReason);
                return null;
            }
        }

        public IMessage GetDraft()
        {
            IMessage msg = new Message();

            if (isReply)
            {
                if (isMail)
                {
                    msg.Receiver = textBox_ReplyTo.Text;
                    msg.Category = Mail.MailCategory;
                }
                else
                {
                    msg.Category = textBox_Board.Text;
                }
            }
            else
            {
                if (isMail)
                {
                    msg.Receiver = textBox_Receiver.Text;
                    msg.Category = Mail.MailCategory;
                }
                else
                {
                    msg.Category = textBox_Board.Text;
                }
            }

            msg.Title = textBox_Title.Text;
            msg.Content = textBox_Contents.Text;
            msg.ViewerGuid = new Guid("751B6808-5676-43b6-B9B7-B167CF9743F4");
            msg.EditorGuid = BbsItemEditorProvider.Guid;

            return msg;
        }

        public bool ImportMessage(IMessage source)
        {
            if (source.ReplyGuid == Guid.Empty || (source.Title.StartsWith("Fw: ")))
            {
                isReply = false;
                bool isMailMode;
                if (Mail.MailCategory.Equals(source.Category))
                {
                    comboBox_Type.SelectedIndex = 1;
                    textBox_Receiver.Text = source.Receiver;

                    isMailMode = true;
                }
                else
                {
                    textBox_Board.Text = source.Category;                    
                    comboBox_Type.SelectedIndex = 0;

                    isMailMode = false;
                }

                SetMailMode(isMailMode);
                comboBox_Type.Enabled = true;
                textBox_Board.ReadOnly = false;
            }
            else
            {
                isReply = true;
                bool isMailMode;
                if (Mail.MailCategory.Equals(source.Category))
                {
                    comboBox_Type.SelectedIndex = 1;
                    textBox_ReplyTo.Text = source.Receiver;

                    isMailMode = true;
                }
                else
                {
                    textBox_ReplyTo.Text = source.Receiver;
                    textBox_Board.Text = source.Category;
                    
                    comboBox_Type.SelectedIndex = 0;

                    isMailMode = false;
                }

                SetMailMode(isMailMode);
                comboBox_Type.Enabled = false;
                textBox_Board.ReadOnly = true;
            }

            textBox_Title.Text = source.Title;
            if (source.Title.StartsWith("Fw:") && source.CustomFields.ContainsKey("PlainText"))
            {
                textBox_Contents.Text = source.CustomFields["PlainText"].Replace("\n",System.Environment.NewLine);

            }
            else
            {
                textBox_Contents.Text = source.Content;
            }

            modified = false;
            return MessageValid;
        }

        public bool MessageModified
        {
            get { return modified; }
            set { modified = value; }
        }

        public bool MessageValid
        {
            get
            {
                if (isReply)
                {

                }
                else
                {
                    if (isMail)
                    {
                        if (textBox_Receiver.Text == null || textBox_Receiver.Text.Trim() == "")
                        {
                            errorReason = "Receiver can not be empty";
                            ShowMessageInvalidReason(textBox_Receiver, errorReason);
                            return false;
                        }

                        if (textBox_Receiver.Text.Length > 20)
                        {
                            errorReason = "Receiver should be a string whose length no larger than 20";
                            ShowMessageInvalidReason(textBox_Receiver, errorReason);
                            return false;
                        }
                    }
                    else
                    {
                        if (textBox_Board.Text == null || textBox_Board.Text.Trim() == "")
                        {
                            errorReason = "Board can not be empty";
                            ShowMessageInvalidReason(textBox_Board, errorReason);
                            return false;
                        }

                        if (textBox_Board.Text.Length > 40)
                        {
                            errorReason = "Board name should be a string whose length no larger than 40";
                            ShowMessageInvalidReason(textBox_Board, errorReason);
                            return false;
                        }
                    }
                }

                if (textBox_Title.Text == null || textBox_Title.Text.Trim() == "")
                {
                    errorReason = "Title can not be empty";
                    ShowMessageInvalidReason(textBox_Title, errorReason);
                    return false;
                }

                if (Character.GetStringLengthInTerm(textBox_Title.Text) >= 80)
                {
                    errorReason = "Title length should be less than 80 (Chinese character counts as two chars)";
                    ShowMessageInvalidReason(textBox_Title, errorReason);
                    return false;
                }


                return true;
            }
        }

        public System.Xml.XPath.XPathNavigator ContextualCommands
        {
            get
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(Properties.Resources.BbsEditorUI);

                return doc.CreateNavigator();
            }
        }

        public void ExcuteCommand(CommandUIEventArgs uiElement)
        {
            if (lastControlFocused is TextBox)
            {
                TextBox txtBox = lastControlFocused as TextBox;

                switch (uiElement.Name)
                {
                    case "Edit.Cut":
                        txtBox.Cut();
                        break;

                    case "Edit.Copy":
                        txtBox.Copy();
                        break;

                    case "Edit.Paste":
                        txtBox.Paste();
                        break;

                    case "Edit.Undo":
                        txtBox.Undo();
                        break;

                    default:
                        return;
                }

                EnableClipboardButtons(txtBox.SelectionLength > 0, txtBox.CanUndo, false);
            }
        }

        public event CommandUIEventHandler UpdateCommandUI;

        private void ShowFieldRows(bool receiver, bool board, bool replyTo)
        {
            if (!receiver)
            {
                tableLayoutPanel_Fields.RowStyles[1].SizeType = SizeType.Absolute;
                tableLayoutPanel_Fields.RowStyles[1].Height = 0;
            }
            else
            {
                tableLayoutPanel_Fields.RowStyles[1].SizeType = SizeType.AutoSize;
            }

            if (!board)
            {
                tableLayoutPanel_Fields.RowStyles[3].SizeType = SizeType.Absolute;
                tableLayoutPanel_Fields.RowStyles[3].Height = 0;
            }
            else
            {
                tableLayoutPanel_Fields.RowStyles[3].SizeType = SizeType.AutoSize;
            }

            if (!replyTo)
            {
                tableLayoutPanel_Fields.RowStyles[2].SizeType = SizeType.Absolute;
                tableLayoutPanel_Fields.RowStyles[2].Height = 0;
            }
            else
            {
                tableLayoutPanel_Fields.RowStyles[2].SizeType = SizeType.AutoSize;
            }

            if (textBox_Receiver.Visible != receiver)
                label_Receiver.Visible = textBox_Receiver.Visible = receiver;
            if (textBox_ReplyTo.Visible != replyTo)
                label_ReplyTo.Visible = textBox_ReplyTo.Visible = replyTo;
            if (textBox_Board.Visible != board)
                label_Board.Visible = textBox_Board.Visible = board;

            this.PerformLayout();
        }

        #endregion

        private void SetMailMode(bool isMailMode)
        {
            if (!isMailMode)
            {
                isMail = false;
                if (isReply)
                {
                    ShowFieldRows(false, true, false);
                }
                else
                {
                    ShowFieldRows(false, true, false);
                }
            }
            else
            {
                isMail = true;
                if (isReply)
                {
                    ShowFieldRows(false, false, true);
                }
                else
                {
                    ShowFieldRows(true, false, false);
                }
            }

            modified = true;
        }

        private void comboBox_Type_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBox_Type.SelectedIndex == 0)
                SetMailMode(false);
            else
                SetMailMode(true);
        }

        private void comboBox_Type_Enter(object sender, EventArgs e)
        {
            lastControlFocused = comboBox_Type;

            DisableClipboardButtons();
        }

        private void textBox_Contents_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                e.Handled = true;
                //MessageBox.Show("hi");
                textBox_Contents.SelectedText = new String(new char[]{Character.ESC});
                textBox_Contents.SelectionStart += textBox_Contents.SelectionLength;
            }
            else if (e.KeyCode == Keys.Enter)
            {
                e.Handled = true;
                textBox_Contents.SelectedText = System.Environment.NewLine;            

            }
        }

        private void BbsItemEditor_Load(object sender, EventArgs e)
        {

        }

        private void EnableAll(bool enable)
        {
            if (UpdateCommandUI != null)
            {
                string[] buttons = new string[]
                {
                      "Font.Family",
                      "Font.HtmlFontSize",
                      "Font.Bold",
                      "Font.Italic",
                      "Font.Underline",
                      "Font.Strikethrough",  
                      "Font.ClearFormat",
                      "Font.Superscript",
                      "Font.Subscript",
                      "Font.ForeColor",
                      "Font.BackColor",
                      "Edit.InsertAttachment",
                      "Paragraph.LeftAlign",
                      "Paragraph.RightAlign",
                      "Paragraph.CenterAlign",  
                      "Paragraph.Numbers",
                      "Paragraph.Bullets",  
                      "Paragraph.Indent",
                      "Paragraph.Unindent"
                };

                foreach (string btn in buttons)
                {
                    CommandUIEventArgs updateArgs = new CommandUIEventArgs();
                    updateArgs.Name = btn;
                    updateArgs.Enabled = enable;
                    updateArgs.Mask = CommandUIMask.None | CommandUIMask.Enabled;

                    this.UpdateCommandUI(this, updateArgs);
                }

            }
        }

        private void BbsItemEditor_ParentChanged(object sender, EventArgs e)
        {
            if (this.Visible)
            {
                EnableAll(false);
                DisableClipboardButtons();

            }
        }

        
    }
}
